home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 42 / Amiga Format AFCD42 (Issue 126, Aug 1999).iso / -serious- / programming / other / jikes / src / scanner.cpp < prev    next >
C/C++ Source or Header  |  1999-05-14  |  55KB  |  1,607 lines

  1. // $Id: scanner.cpp,v 1.5 1999/02/17 19:07:57 shields Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10. #include "config.h"
  11. #include "scanner.h"
  12. #include "control.h"
  13. #include "error.h"
  14.  
  15. int (*Scanner::scan_keyword[13]) (wchar_t *p1) =
  16. {
  17.     ScanKeyword0,
  18.     ScanKeyword0,
  19.     ScanKeyword2,
  20.     ScanKeyword3,
  21.     ScanKeyword4,
  22.     ScanKeyword5,
  23.     ScanKeyword6,
  24.     ScanKeyword7,
  25.     ScanKeyword8,
  26.     ScanKeyword9,
  27.     ScanKeyword10,
  28.     ScanKeyword0,
  29.     ScanKeyword12
  30. };
  31.  
  32.  
  33. //
  34. // The constructor initializes all utility variables.
  35. //
  36. Scanner::Scanner(Control &control_) : control(control_)
  37. {
  38.     //
  39.     // If this assertion fails, the Token structure in stream.h must be redesigned !!!
  40.     //
  41.     assert(NUM_TERMINALS < 128);
  42.  
  43.     //
  44.     // -------------------------------------------------------------------------------
  45.     // We are pulling this code out because we are tired of defending it. We
  46.     // tought it was obvious that either $ should not have been used for compiler
  47.     // generated variables or that users should not be allowed to use in variable names...
  48.     // -------------------------------------------------------------------------------
  49.     //
  50.     // For version 1.1 or above a $ may not be used as part of an identifier name
  51.     // unless the user specifically requests that it be allowed.
  52.     //
  53.     //    if (control.option.one_one && (! control.option.dollar))
  54.     //        Code::SetBadCode(U_DOLLAR);
  55.     //
  56.  
  57.     //
  58.     // CLASSIFY_TOKEN is a mapping from each character into a     
  59.     // classification routine that is invoked when that character 
  60.     // is the first character encountered in a token.             
  61.     //
  62.     for (int c = 0; c < 128; c++)
  63.     {
  64.         if (Code::IsAlpha(c))
  65.              classify_token[c] = &Scanner::ClassifyId;
  66.         else if (Code::IsDigit(c))
  67.              classify_token[c] = &Scanner::ClassifyNumericLiteral;
  68.         else classify_token[c] = &Scanner::ClassifyBadToken;
  69.     }
  70.     classify_token[128] = &Scanner::ClassifyNonAsciiUnicode;
  71.  
  72.     classify_token[U_a] = &Scanner::ClassifyIdOrKeyword;
  73.     classify_token[U_b] = &Scanner::ClassifyIdOrKeyword;
  74.     classify_token[U_c] = &Scanner::ClassifyIdOrKeyword;
  75.     classify_token[U_d] = &Scanner::ClassifyIdOrKeyword;
  76.     classify_token[U_e] = &Scanner::ClassifyIdOrKeyword;
  77.     classify_token[U_f] = &Scanner::ClassifyIdOrKeyword;
  78.     classify_token[U_g] = &Scanner::ClassifyIdOrKeyword;
  79.     classify_token[U_i] = &Scanner::ClassifyIdOrKeyword;
  80.     classify_token[U_l] = &Scanner::ClassifyIdOrKeyword;
  81.     classify_token[U_n] = &Scanner::ClassifyIdOrKeyword;
  82.     classify_token[U_p] = &Scanner::ClassifyIdOrKeyword;
  83.     classify_token[U_r] = &Scanner::ClassifyIdOrKeyword;
  84.     classify_token[U_s] = &Scanner::ClassifyIdOrKeyword;
  85.     classify_token[U_t] = &Scanner::ClassifyIdOrKeyword;
  86.     classify_token[U_v] = &Scanner::ClassifyIdOrKeyword;
  87.     classify_token[U_w] = &Scanner::ClassifyIdOrKeyword;
  88.     
  89.     classify_token[U_SINGLE_QUOTE]       = &Scanner::ClassifyCharLiteral;
  90.     classify_token[U_DOUBLE_QUOTE]       = &Scanner::ClassifyStringLiteral;
  91.  
  92.     classify_token[U_PLUS]               = &Scanner::ClassifyPlus;
  93.     classify_token[U_MINUS]              = &Scanner::ClassifyMinus;
  94.     classify_token[U_EXCLAMATION]        = &Scanner::ClassifyNot;
  95.     classify_token[U_PERCENT]            = &Scanner::ClassifyMod;
  96.     classify_token[U_CARET]              = &Scanner::ClassifyXor;
  97.     classify_token[U_AMPERSAND]          = &Scanner::ClassifyAnd;
  98.     classify_token[U_STAR]               = &Scanner::ClassifyStar;
  99.     classify_token[U_BAR]                = &Scanner::ClassifyOr;
  100.     classify_token[U_TILDE]              = &Scanner::ClassifyComplement;
  101.     classify_token[U_SLASH]              = &Scanner::ClassifySlash;
  102.     classify_token[U_GREATER]            = &Scanner::ClassifyGreater;
  103.     classify_token[U_LESS]               = &Scanner::ClassifyLess;
  104.     classify_token[U_LEFT_PARENTHESIS]   = &Scanner::ClassifyLparen;
  105.     classify_token[U_RIGHT_PARENTHESIS]  = &Scanner::ClassifyRparen;
  106.     classify_token[U_LEFT_BRACE]         = &Scanner::ClassifyLbrace;
  107.     classify_token[U_RIGHT_BRACE]        = &Scanner::ClassifyRbrace;
  108.     classify_token[U_LEFT_BRACKET]       = &Scanner::ClassifyLbracket;
  109.     classify_token[U_RIGHT_BRACKET]      = &Scanner::ClassifyRbracket;
  110.     classify_token[U_SEMICOLON]          = &Scanner::ClassifySemicolon;
  111.     classify_token[U_QUESTION]           = &Scanner::ClassifyQuestion;
  112.     classify_token[U_COLON]              = &Scanner::ClassifyColon;
  113.     classify_token[U_COMMA]              = &Scanner::ClassifyComma;
  114.     classify_token[U_DOT]                = &Scanner::ClassifyPeriod;
  115.     classify_token[U_EQUAL]              = &Scanner::ClassifyEqual;
  116.  
  117.     return;
  118. }
  119.  
  120.  
  121. //
  122. // Associate a lexical stream with this file
  123. //
  124. void Scanner::Initialize(FileSymbol *file_symbol)
  125. {
  126.     lex = new LexStream(control, file_symbol);
  127.     lex -> Reset();
  128.  
  129.     LexStream::Token *current_token = &(lex -> token_stream.Next()); // add 0th token !
  130.     current_token -> SetKind(0);
  131.     current_token -> SetLocation(0);
  132.     current_token -> SetSymbol(NULL);
  133.  
  134.     if (control.option.comments)
  135.     {
  136.         LexStream::Comment *current_comment = &(lex -> comment_stream.Next()); // add 0th comment !
  137.         current_comment -> string = NULL;
  138.         current_comment -> length = 0;
  139.         current_comment -> previous_token = -1; // No token precedes this comment
  140.         current_comment -> location = 0;
  141.     }
  142.  
  143.     lex -> line_location.Next() = 0; // mark starting location of line # 0
  144.  
  145.     return;
  146. }
  147.  
  148.  
  149. //
  150. // This is one of the main entry point for the Java lexical analyser.
  151. // Its input is the name of a regular text file. Its output is a stream
  152. // of tokens.
  153. //
  154. void Scanner::SetUp(FileSymbol *file_symbol)
  155. {
  156.     Initialize(file_symbol);
  157.     lex -> CompressSpace();
  158.     file_symbol -> lex_stream = lex;
  159.  
  160.     return;
  161. }
  162.  
  163.  
  164. //
  165. // This is one of the main entry point for the Java lexical analyser.
  166. // Its input is the name of a regular text file. Its output is a stream
  167. // of tokens.
  168. //
  169. void Scanner::Scan(FileSymbol *file_symbol)
  170. {
  171.     Initialize(file_symbol);
  172.  
  173.     lex -> ReadInput();
  174.  
  175.     cursor = lex -> InputBuffer();
  176.     if (cursor)
  177.     {
  178.         Scan();
  179.         lex -> CompressSpace();
  180.  
  181.         //
  182.         //
  183.         //
  184.         if (control.option.dump_errors)
  185.         {
  186.             lex -> SortMessages();
  187.             for (int i = 0; i < lex -> bad_tokens.Length(); i++) 
  188.                 lex -> PrintEmacsMessage(i);
  189.             cout.flush();
  190.         }
  191.         lex -> DestroyInput(); // get rid of input buffer
  192.     }
  193.     else
  194.     {
  195.         delete lex;
  196.         lex = NULL;
  197.     }
  198.  
  199.     file_symbol -> lex_stream = lex;
  200.  
  201.     return;
  202. }
  203.  
  204.  
  205. //
  206. // Scan the InputBuffer() and process all tokens and comments.
  207. //
  208. void Scanner::Scan()
  209. {
  210.     wchar_t *input_buffer_tail = &cursor[lex -> InputBufferLength()];
  211.  
  212.     //
  213.     // CURSOR is assumed to point to the next character to be scanned.
  214.     // Using CURSOR,we jump to the proper classification function
  215.     // which scans and classifies the token and returns the location of
  216.     // the character immediately following it.
  217.     //
  218.     do
  219.     {
  220.         SkipSpaces();
  221.         (this ->* classify_token[*cursor < 128 ? *cursor : 128])();
  222.     } while (cursor < input_buffer_tail);
  223.  
  224.     //
  225.     // Add a a gate after the last line.
  226.     //
  227.     lex -> line_location.Next() = input_buffer_tail - lex -> InputBuffer();
  228.  
  229.     //
  230.     // If the brace_stack is not empty, then there are unmatched left
  231.     // braces in the input. Each unmatched left brace should point to 
  232.     // the EOF token as a substitute for a matching right brace.
  233.     //
  234.     for (LexStream::TokenIndex left_brace = brace_stack.Top(); left_brace; left_brace = brace_stack.Top())
  235.     {
  236.         lex -> token_stream[left_brace].SetRightBrace(lex -> token_stream.Length() - 1);
  237.         brace_stack.Pop();
  238.     }
  239.  
  240.     return;
  241. }
  242.  
  243.  
  244. //
  245. // CURSOR points to the s